{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# ABU量化系统使用文档 \n",
    "\n",
    "<center>\n",
    "        <img src=\"./image/abu_logo.png\" alt=\"\" style=\"vertical-align:middle;padding:10px 20px;\"><font size=\"6\" color=\"black\"><b>第21节 A股UMP决策</b></font>\n",
    "</center>\n",
    "\n",
    "-----------------\n",
    "\n",
    "作者: 阿布\n",
    "\n",
    "阿布量化版权所有 未经允许 禁止转载\n",
    "\n",
    "[abu量化系统github地址](https://github.com/bbfamily/abu) (欢迎+star)\n",
    "\n",
    "[本节ipython notebook](https://github.com/bbfamily/abu/tree/master/abupy_lecture)\n",
    "\n",
    "上一节通过切割A股市场训练集测试集symbol，分别对切割的训练集和测试集做了回测，本节将示例A股ump主裁，边裁决策。\n",
    "\n",
    "首先导入abupy中本节使用的模块："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "enable example env will only read RomDataBu/df_kl.h5\n"
     ]
    }
   ],
   "source": [
    "# 基础库导入\n",
    "\n",
    "from __future__ import print_function\n",
    "from __future__ import division\n",
    "\n",
    "import warnings\n",
    "warnings.filterwarnings('ignore')\n",
    "warnings.simplefilter('ignore')\n",
    "\n",
    "import numpy as np\n",
    "import pandas as pd\n",
    "import matplotlib.pyplot as plt\n",
    "import ipywidgets\n",
    "%matplotlib inline\n",
    "\n",
    "import os\n",
    "import sys\n",
    "# 使用insert 0即只使用github，避免交叉使用了pip安装的abupy，导致的版本不一致问题\n",
    "sys.path.insert(0, os.path.abspath('../'))\n",
    "import abupy\n",
    "\n",
    "# 使用沙盒数据，目的是和书中一样的数据环境\n",
    "abupy.env.enable_example_env_ipython()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "disable example env\n"
     ]
    }
   ],
   "source": [
    "from abupy import AbuFactorAtrNStop, AbuFactorPreAtrNStop, AbuFactorCloseAtrNStop, AbuFactorBuyBreak\n",
    "from abupy import abu, EMarketTargetType, AbuMetricsBase, ABuMarketDrawing, ABuProgress, ABuSymbolPd\n",
    "from abupy import EMarketTargetType, EDataCacheType, EMarketSourceType, EMarketDataFetchMode, EStoreAbu, AbuUmpMainMul\n",
    "from abupy import AbuUmpMainDeg, AbuUmpMainJump, AbuUmpMainPrice, AbuUmpMainWave, feature, AbuFeatureDegExtend\n",
    "from abupy import AbuUmpEdgeDeg, AbuUmpEdgePrice, AbuUmpEdgeWave, AbuUmpEdgeFull, AbuUmpEdgeMul, AbuUmpEegeDegExtend\n",
    "from abupy import AbuUmpMainDegExtend, ump, Parallel, delayed, AbuMulPidProgress\n",
    "\n",
    "# 关闭沙盒数据\n",
    "abupy.env.disable_example_env_ipython()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "下面读取上一节存储的训练集和测试集回测数据，如下所示："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "训练集结果：\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "买入后卖出的交易数量:55224\n",
      "买入后尚未卖出的交易数量:951\n",
      "胜率:47.1353%\n",
      "平均获利期望:16.5030%\n",
      "平均亏损期望:-7.7784%\n",
      "盈亏比:1.9844\n",
      "所有交易收益比例和:2035.3322 \n",
      "所有交易总盈亏和:42576596.8500 \n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "测试集结果：\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "买入后卖出的交易数量:6321\n",
      "买入后尚未卖出的交易数量:124\n",
      "胜率:47.6507%\n",
      "平均获利期望:15.7211%\n",
      "平均亏损期望:-7.6456%\n",
      "盈亏比:2.0477\n",
      "所有交易收益比例和:221.5061 \n",
      "所有交易总盈亏和:44078404.6500 \n"
     ]
    }
   ],
   "source": [
    "abupy.env.g_market_target = EMarketTargetType.E_MARKET_TARGET_CN\n",
    "abupy.env.g_data_fetch_mode = EMarketDataFetchMode.E_DATA_FETCH_FORCE_LOCAL\n",
    "abu_result_tuple = abu.load_abu_result_tuple(n_folds=5, store_type=EStoreAbu.E_STORE_CUSTOM_NAME, \n",
    "                                             custom_name='train_cn')\n",
    "abu_result_tuple_test = abu.load_abu_result_tuple(n_folds=5, store_type=EStoreAbu.E_STORE_CUSTOM_NAME, \n",
    "                                             custom_name='test_cn')\n",
    "ABuProgress.clear_output()\n",
    "print('训练集结果：')\n",
    "metrics_train = AbuMetricsBase.show_general(*abu_result_tuple, returns_cmp=True ,only_info=True)\n",
    "print('测试集结果：')\n",
    "metrics_test  = AbuMetricsBase.show_general(*abu_result_tuple_test, returns_cmp=True, only_info=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "### 1. A股训练集主裁训练\n",
    "\n",
    "下面开始使用训练集交易数据训练主裁，裁判组合使用两个abupy中内置裁判AbuUmpMainDeg和AbuUmpMainPrice，两个外部自定义裁判使用‘第18节 自定义裁判决策交易‘中编写的AbuUmpMainMul和AbuUmpMainDegExtend\n",
    "\n",
    "第一次运行select：train main ump，然后点击run select，如果已经训练过可select：load main ump直接读取以训练好的主裁："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "load main ump complete!\n"
     ]
    }
   ],
   "source": [
    "# 需要全局设置为A股市场，在ump会根据市场类型保存读取对应的ump\n",
    "abupy.env.g_market_target = EMarketTargetType.E_MARKET_TARGET_CN\n",
    "ump_deg=None\n",
    "ump_mul=None\n",
    "ump_price=None\n",
    "ump_main_deg_extend=None\n",
    "# 使用训练集交易数据训练主裁\n",
    "orders_pd_train_cn = abu_result_tuple.orders_pd\n",
    "\n",
    "def train_main_ump():\n",
    "    print('AbuUmpMainDeg begin...')\n",
    "    AbuUmpMainDeg.ump_main_clf_dump(orders_pd_train_cn, save_order=False, show_order=False)\n",
    "    print('AbuUmpMainPrice begin...')\n",
    "    AbuUmpMainPrice.ump_main_clf_dump(orders_pd_train_cn, save_order=False, show_order=False)\n",
    "    print('AbuUmpMainMul begin...')\n",
    "    AbuUmpMainMul.ump_main_clf_dump(orders_pd_train_cn, save_order=False, show_order=False)\n",
    "    print('AbuUmpMainDegExtend begin...')\n",
    "    AbuUmpMainDegExtend.ump_main_clf_dump(orders_pd_train_cn, save_order=False, show_order=False)\n",
    "    # 依然使用load_main_ump，避免下面多进程内存拷贝过大\n",
    "    load_main_ump()\n",
    "    \n",
    "def load_main_ump():\n",
    "    global ump_deg, ump_mul, ump_price, ump_main_deg_extend\n",
    "    ump_deg = AbuUmpMainDeg(predict=True)\n",
    "    ump_mul = AbuUmpMainMul(predict=True)\n",
    "    ump_price = AbuUmpMainPrice(predict=True)\n",
    "    ump_main_deg_extend = AbuUmpMainDegExtend(predict=True)\n",
    "    print('load main ump complete!')\n",
    "\n",
    "def select(select):\n",
    "    if select == 'train main ump':\n",
    "        train_main_ump()\n",
    "    else:\n",
    "        load_main_ump()\n",
    "\n",
    "_ = ipywidgets.interact_manual(select, select=['train main ump', 'load main ump'])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "### 2. 验证A股主裁是否称职"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "下面首先通过从测试集交易中筛选出来已经有交易结果的交易，如下："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# 选取有交易结果的数据order_has_result\n",
    "order_has_result = abu_result_tuple_test.orders_pd[abu_result_tuple_test.orders_pd.result != 0]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "order_has_result的交易单中记录了所买入时刻的交易特征，如下所示："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>buy_deg_ang42</th>\n",
       "      <th>buy_deg_ang252</th>\n",
       "      <th>buy_deg_ang60</th>\n",
       "      <th>buy_deg_ang21</th>\n",
       "      <th>buy_price_rank120</th>\n",
       "      <th>buy_price_rank90</th>\n",
       "      <th>buy_price_rank60</th>\n",
       "      <th>buy_price_rank252</th>\n",
       "      <th>buy_wave_score1</th>\n",
       "      <th>buy_wave_score2</th>\n",
       "      <th>buy_wave_score3</th>\n",
       "      <th>buy_jump_down_power</th>\n",
       "      <th>buy_jump_up_power</th>\n",
       "      <th>buy_deg_ang10</th>\n",
       "      <th>buy_deg_ang50</th>\n",
       "      <th>buy_deg_ang120</th>\n",
       "      <th>buy_deg_ang90</th>\n",
       "      <th>buy_deg_ang30</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>2012-10-12</th>\n",
       "      <td>5.256</td>\n",
       "      <td>18.442</td>\n",
       "      <td>1.923</td>\n",
       "      <td>0.424</td>\n",
       "      <td>0.992</td>\n",
       "      <td>0.989</td>\n",
       "      <td>0.983</td>\n",
       "      <td>0.996</td>\n",
       "      <td>0.164</td>\n",
       "      <td>0.086</td>\n",
       "      <td>0.160</td>\n",
       "      <td>0.000</td>\n",
       "      <td>0.000</td>\n",
       "      <td>1.641</td>\n",
       "      <td>4.476</td>\n",
       "      <td>14.184</td>\n",
       "      <td>1.610</td>\n",
       "      <td>5.445</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2012-10-12</th>\n",
       "      <td>1.188</td>\n",
       "      <td>3.530</td>\n",
       "      <td>-1.666</td>\n",
       "      <td>0.182</td>\n",
       "      <td>0.992</td>\n",
       "      <td>0.989</td>\n",
       "      <td>0.983</td>\n",
       "      <td>0.974</td>\n",
       "      <td>0.582</td>\n",
       "      <td>0.485</td>\n",
       "      <td>0.430</td>\n",
       "      <td>0.000</td>\n",
       "      <td>1.109</td>\n",
       "      <td>4.569</td>\n",
       "      <td>-1.449</td>\n",
       "      <td>4.277</td>\n",
       "      <td>2.321</td>\n",
       "      <td>5.302</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2012-10-12</th>\n",
       "      <td>5.158</td>\n",
       "      <td>-13.777</td>\n",
       "      <td>-2.700</td>\n",
       "      <td>4.242</td>\n",
       "      <td>0.433</td>\n",
       "      <td>0.556</td>\n",
       "      <td>0.825</td>\n",
       "      <td>0.363</td>\n",
       "      <td>0.124</td>\n",
       "      <td>0.113</td>\n",
       "      <td>0.148</td>\n",
       "      <td>-1.462</td>\n",
       "      <td>1.145</td>\n",
       "      <td>6.877</td>\n",
       "      <td>3.386</td>\n",
       "      <td>-10.600</td>\n",
       "      <td>-10.429</td>\n",
       "      <td>3.809</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2012-10-12</th>\n",
       "      <td>12.439</td>\n",
       "      <td>-17.173</td>\n",
       "      <td>9.696</td>\n",
       "      <td>2.072</td>\n",
       "      <td>1.000</td>\n",
       "      <td>1.000</td>\n",
       "      <td>1.000</td>\n",
       "      <td>0.821</td>\n",
       "      <td>1.895</td>\n",
       "      <td>2.026</td>\n",
       "      <td>2.060</td>\n",
       "      <td>0.000</td>\n",
       "      <td>0.000</td>\n",
       "      <td>13.114</td>\n",
       "      <td>13.611</td>\n",
       "      <td>-5.619</td>\n",
       "      <td>-0.506</td>\n",
       "      <td>1.480</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2012-10-12</th>\n",
       "      <td>-2.753</td>\n",
       "      <td>-20.287</td>\n",
       "      <td>-2.827</td>\n",
       "      <td>-2.386</td>\n",
       "      <td>0.542</td>\n",
       "      <td>0.722</td>\n",
       "      <td>1.000</td>\n",
       "      <td>0.270</td>\n",
       "      <td>0.771</td>\n",
       "      <td>0.313</td>\n",
       "      <td>0.151</td>\n",
       "      <td>-1.288</td>\n",
       "      <td>1.819</td>\n",
       "      <td>5.374</td>\n",
       "      <td>-2.946</td>\n",
       "      <td>-15.839</td>\n",
       "      <td>-9.822</td>\n",
       "      <td>-0.243</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "            buy_deg_ang42  buy_deg_ang252  buy_deg_ang60  buy_deg_ang21  \\\n",
       "2012-10-12          5.256          18.442          1.923          0.424   \n",
       "2012-10-12          1.188           3.530         -1.666          0.182   \n",
       "2012-10-12          5.158         -13.777         -2.700          4.242   \n",
       "2012-10-12         12.439         -17.173          9.696          2.072   \n",
       "2012-10-12         -2.753         -20.287         -2.827         -2.386   \n",
       "\n",
       "            buy_price_rank120  buy_price_rank90  buy_price_rank60  \\\n",
       "2012-10-12              0.992             0.989             0.983   \n",
       "2012-10-12              0.992             0.989             0.983   \n",
       "2012-10-12              0.433             0.556             0.825   \n",
       "2012-10-12              1.000             1.000             1.000   \n",
       "2012-10-12              0.542             0.722             1.000   \n",
       "\n",
       "            buy_price_rank252  buy_wave_score1  buy_wave_score2  \\\n",
       "2012-10-12              0.996            0.164            0.086   \n",
       "2012-10-12              0.974            0.582            0.485   \n",
       "2012-10-12              0.363            0.124            0.113   \n",
       "2012-10-12              0.821            1.895            2.026   \n",
       "2012-10-12              0.270            0.771            0.313   \n",
       "\n",
       "            buy_wave_score3  buy_jump_down_power  buy_jump_up_power  \\\n",
       "2012-10-12            0.160                0.000              0.000   \n",
       "2012-10-12            0.430                0.000              1.109   \n",
       "2012-10-12            0.148               -1.462              1.145   \n",
       "2012-10-12            2.060                0.000              0.000   \n",
       "2012-10-12            0.151               -1.288              1.819   \n",
       "\n",
       "            buy_deg_ang10  buy_deg_ang50  buy_deg_ang120  buy_deg_ang90  \\\n",
       "2012-10-12          1.641          4.476          14.184          1.610   \n",
       "2012-10-12          4.569         -1.449           4.277          2.321   \n",
       "2012-10-12          6.877          3.386         -10.600        -10.429   \n",
       "2012-10-12         13.114         13.611          -5.619         -0.506   \n",
       "2012-10-12          5.374         -2.946         -15.839         -9.822   \n",
       "\n",
       "            buy_deg_ang30  \n",
       "2012-10-12          5.445  \n",
       "2012-10-12          5.302  \n",
       "2012-10-12          3.809  \n",
       "2012-10-12          1.480  \n",
       "2012-10-12         -0.243  "
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "order_has_result.filter(regex='^buy(_deg_|_price_|_wave_|_jump)').head()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "可以通过一个一个迭代交易单，将交易单中的买入时刻特征传递给ump主裁决策器，让每一个主裁来决策是否进行拦截，这样可以统计每一个主裁的拦截成功率，以及整体拦截率等，如下所示：\n",
    "\n",
    "备注：\n",
    "\n",
    "* 如下的代码使用abupy中再次封装joblib的多进程调度使用示例，以及abupy中封装的多进程进度条的使用示例\n",
    "* 3.4下由于子进程中pickle ump的内部类会找不到，所以暂时只使用一个进程一个一个的处理"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "pid:18298 ump_deg complete:99.67%\n",
      "pid:18298 done!\n"
     ]
    }
   ],
   "source": [
    "def apply_ml_features_ump(order, predicter, progress, need_hit_cnt):\n",
    "    if not isinstance(order.ml_features, dict):\n",
    "        import ast\n",
    "        # 低版本pandas dict对象取出来会成为str\n",
    "        ml_features = ast.literal_eval(order.ml_features)\n",
    "    else:\n",
    "        ml_features = order.ml_features\n",
    "    progress.show()\n",
    "    # 将交易单中的买入时刻特征传递给ump主裁决策器，让每一个主裁来决策是否进行拦截\n",
    "    return predicter.predict_kwargs(need_hit_cnt=need_hit_cnt, **ml_features)\n",
    "\n",
    "def pararllel_func(ump_object, ump_name):\n",
    "    with AbuMulPidProgress(len(order_has_result), '{} complete'.format(ump_name)) as progress:\n",
    "        # 启动多进程进度条，对order_has_result进行apply\n",
    "        ump_result = order_has_result.apply(apply_ml_features_ump, axis=1, args=(ump_object, progress, 2,))\n",
    "    return ump_name, ump_result\n",
    "\n",
    "if sys.version_info > (3, 4, 0):\n",
    "    # python3.4以上并行处理4个主裁，每一个主裁启动一个进程进行拦截决策\n",
    "    parallel = Parallel(\n",
    "        n_jobs=4, verbose=0, pre_dispatch='2*n_jobs')\n",
    "    out = parallel(delayed(pararllel_func)(ump_object, ump_name)\n",
    "                                  for ump_object, ump_name in zip([ump_deg, ump_mul, ump_price, ump_main_deg_extend], \n",
    "                                                           ['ump_deg', 'ump_mul', 'ump_price', 'ump_main_deg_extend']))\n",
    "else:\n",
    "    # 3.4下由于子进程中pickle ump的内部类会找不到，所以暂时只使用一个进程一个一个的处理\n",
    "    out = [pararllel_func(ump_object, ump_name) for ump_object, ump_name in zip([ump_deg, ump_mul, ump_price, ump_main_deg_extend], \n",
    "                                                           ['ump_deg', 'ump_mul', 'ump_price', 'ump_main_deg_extend'])]\n",
    "\n",
    "# 将每一个进程中的裁判的拦截决策进行汇总\n",
    "for sub_out in out:\n",
    "    order_has_result[sub_out[0]] = sub_out[1]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "通过把所有主裁的决策进行相加, 如果有投票1的即会进行拦截，四个裁判整体拦截正确率统计："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "四个裁判整体拦截正确率61.71%\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>ump_deg</th>\n",
       "      <th>ump_mul</th>\n",
       "      <th>ump_price</th>\n",
       "      <th>ump_main_deg_extend</th>\n",
       "      <th>sum_bk</th>\n",
       "      <th>result</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>2017-07-20</th>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>4</td>\n",
       "      <td>-1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2017-07-21</th>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>3</td>\n",
       "      <td>-1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2017-07-21</th>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>3</td>\n",
       "      <td>-1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2017-08-01</th>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>3</td>\n",
       "      <td>-1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2017-08-03</th>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>3</td>\n",
       "      <td>-1</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "            ump_deg  ump_mul  ump_price  ump_main_deg_extend  sum_bk  result\n",
       "2017-07-20        1        1          1                    1       4      -1\n",
       "2017-07-21        0        1          1                    1       3      -1\n",
       "2017-07-21        0        1          1                    1       3      -1\n",
       "2017-08-01        0        1          1                    1       3      -1\n",
       "2017-08-03        0        1          1                    1       3      -1"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "block_pd = order_has_result.filter(regex='^ump_*')\n",
    "# 把所有主裁的决策进行相加\n",
    "block_pd['sum_bk'] = block_pd.sum(axis=1)\n",
    "block_pd['result'] = order_has_result['result']\n",
    "# 有投票1的即会进行拦截\n",
    "block_pd = block_pd[block_pd.sum_bk > 0]\n",
    "print('四个裁判整体拦截正确率{:.2f}%'.format(block_pd[block_pd.result == -1].result.count() / block_pd.result.count() * 100))\n",
    "block_pd.tail()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "下面统计每一个主裁的拦截正确率："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "角度裁判拦截正确率65.09%, 拦截交易数量974\n",
      "角度扩展裁判拦拦截正确率65.64%, 拦截交易数量1039\n",
      "单混裁判拦截正确率63.30%, 拦截交易数量534\n",
      "价格裁判拦截正确率64.57%, 拦截交易数量796\n"
     ]
    }
   ],
   "source": [
    "from sklearn import metrics\n",
    "def sub_ump_show(block_name):\n",
    "    sub_block_pd = block_pd[(block_pd[block_name] == 1)]\n",
    "    # 如果失败就正确 －1->1 1->0\n",
    "    sub_block_pd.result = np.where(sub_block_pd.result == -1, 1, 0)\n",
    "    return metrics.accuracy_score(sub_block_pd[block_name], sub_block_pd.result) * 100, sub_block_pd.result.count()\n",
    "\n",
    "print('角度裁判拦截正确率{:.2f}%, 拦截交易数量{}'.format(*sub_ump_show('ump_deg')))\n",
    "print('角度扩展裁判拦拦截正确率{:.2f}%, 拦截交易数量{}'.format(*sub_ump_show('ump_main_deg_extend')))\n",
    "print('单混裁判拦截正确率{:.2f}%, 拦截交易数量{}'.format(*sub_ump_show('ump_mul')))\n",
    "print('价格裁判拦截正确率{:.2f}%, 拦截交易数量{}'.format(*sub_ump_show('ump_price')))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3. A股训练集边裁训练\n",
    "\n",
    "下面开始使用训练集交易数据训练训裁，裁判组合依然使用两个abupy中内置裁判AbuUmpEdgeDeg和AbuUmpEdgePrice，两个外部自定义裁判使用‘第18节 自定义裁判决策交易‘中编写的AbuUmpEdgeMul和AbuUmpEegeDegExtend，如下所示\n",
    "\n",
    "备注：由于边裁的运行机制，所以边裁的训练非常快，这里直接进行训练，不再从本地读取裁判决策数据"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "AbuUmpEdgeDeg begin...\n",
      "please wait! dump_pickle....: /Users/Bailey/abu/data/ump/ump_edge_hs_deg_edge\n",
      "AbuUmpEdgePrice begin...\n",
      "please wait! dump_pickle....: /Users/Bailey/abu/data/ump/ump_edge_hs_price_edge\n",
      "AbuUmpEdgeMul begin...\n",
      "please wait! dump_pickle....: /Users/Bailey/abu/data/ump/ump_edge_hs_mul_edge\n",
      "AbuUmpEegeDegExtend begin...\n",
      "please wait! dump_pickle....: /Users/Bailey/abu/data/ump/ump_edge_hs_extend_edge_deg\n",
      "fit edge complete!\n"
     ]
    }
   ],
   "source": [
    "# 需要全局设置为A股市场，在ump会根据市场类型保存读取对应的ump\n",
    "abupy.env.g_market_target = EMarketTargetType.E_MARKET_TARGET_CN\n",
    "\n",
    "print('AbuUmpEdgeDeg begin...')\n",
    "AbuUmpEdgeDeg.ump_edge_clf_dump(orders_pd_train_cn)\n",
    "edge_deg = AbuUmpEdgeDeg(predict=True)\n",
    "\n",
    "print('AbuUmpEdgePrice begin...')\n",
    "AbuUmpEdgePrice.ump_edge_clf_dump(orders_pd_train_cn)\n",
    "edge_price = AbuUmpEdgePrice(predict=True)\n",
    "\n",
    "print('AbuUmpEdgeMul begin...')\n",
    "AbuUmpEdgeMul.ump_edge_clf_dump(orders_pd_train_cn)\n",
    "edge_mul = AbuUmpEdgeMul(predict=True)\n",
    "\n",
    "print('AbuUmpEegeDegExtend begin...')\n",
    "AbuUmpEegeDegExtend.ump_edge_clf_dump(orders_pd_train_cn)\n",
    "edge_deg_extend = AbuUmpEegeDegExtend(predict=True)\n",
    "\n",
    "print('fit edge complete!')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 4. 验证A股边裁是否称职"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "使用与主裁类似的方式，一个一个迭代交易单，将交易单中的买入时刻特征传递给ump边裁决策器，让每一个边裁来决策是否进行拦截，统计每一个边裁的拦截成功率，以及整体拦截率等，如下所示：\n",
    "\n",
    "备注：如下的代码使用abupy中再次封装joblib的多进程调度使用示例，以及abupy中封装的多进程进度条的使用示例"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "pid:18632 edge_mul complete:99.67%\n",
      "pid:18632 done!\n"
     ]
    }
   ],
   "source": [
    "def apply_ml_features_edge(order, predicter, progress):\n",
    "    if not isinstance(order.ml_features, dict):\n",
    "        import ast\n",
    "        # 低版本pandas dict对象取出来会成为str\n",
    "        ml_features = ast.literal_eval(order.ml_features)\n",
    "    else:\n",
    "        ml_features = order.ml_features\n",
    "    # 边裁进行裁决\n",
    "    progress.show()\n",
    "    # 将交易单中的买入时刻特征传递给ump边裁决策器，让每一个边裁来决策是否进行拦截\n",
    "    edge = predicter.predict(**ml_features)\n",
    "    return edge.value\n",
    "\n",
    "\n",
    "def edge_pararllel_func(edge, edge_name):\n",
    "    with AbuMulPidProgress(len(order_has_result), '{} complete'.format(edge_name)) as progress:\n",
    "        # # 启动多进程进度条，对order_has_result进行apply\n",
    "        edge_result = order_has_result.apply(apply_ml_features_edge, axis=1, args=(edge, progress,))\n",
    "    return edge_name, edge_result\n",
    "\n",
    "if sys.version_info > (3, 4, 0):\n",
    "    # python3.4以上并行处理4个边裁的决策，每一个边裁启动一个进程进行拦截决策\n",
    "    parallel = Parallel(\n",
    "        n_jobs=4, verbose=0, pre_dispatch='2*n_jobs')\n",
    "    out = parallel(delayed(edge_pararllel_func)(edge, edge_name)\n",
    "                                  for edge, edge_name in zip([edge_deg, edge_price, edge_mul, edge_deg_extend], \n",
    "                                                           ['edge_deg', 'edge_price', 'edge_mul', 'edge_deg_extend']))\n",
    "else:\n",
    "    # 3.4下由于子进程中pickle ump的内部类会找不到，所以暂时只使用一个进程一个一个的处理\n",
    "    out = [edge_pararllel_func(edge, edge_name) for edge, edge_name in zip([edge_deg, edge_price, edge_mul, edge_deg_extend], \n",
    "                                                           ['edge_deg', 'edge_price', 'edge_mul', 'edge_deg_extend'])]\n",
    "     \n",
    "# 将每一个进程中的裁判的拦截决策进行汇总\n",
    "for sub_out in out:\n",
    "    order_has_result[sub_out[0]] = sub_out[1]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "通过把所有边裁的决策进行统计, 如果有投票-1的结果即判定loss_top的拿出来和真实交易结果result组成结果集，统计四个边裁的整体拦截正确率以及拦截率，如下所示："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "四个裁判整体拦截正确率59.53%\n",
      "四个边裁拦截交易总数2874， 拦截率45.47%\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>edge_deg</th>\n",
       "      <th>edge_price</th>\n",
       "      <th>edge_mul</th>\n",
       "      <th>edge_deg_extend</th>\n",
       "      <th>edge_block</th>\n",
       "      <th>result</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>2012-10-12</th>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>-1</td>\n",
       "      <td>0</td>\n",
       "      <td>-1</td>\n",
       "      <td>-1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2012-10-12</th>\n",
       "      <td>-1</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>-1</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2012-10-12</th>\n",
       "      <td>0</td>\n",
       "      <td>-1</td>\n",
       "      <td>-1</td>\n",
       "      <td>0</td>\n",
       "      <td>-1</td>\n",
       "      <td>-1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2012-10-12</th>\n",
       "      <td>-1</td>\n",
       "      <td>-1</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>-1</td>\n",
       "      <td>-1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2012-10-12</th>\n",
       "      <td>0</td>\n",
       "      <td>-1</td>\n",
       "      <td>-1</td>\n",
       "      <td>0</td>\n",
       "      <td>-1</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "            edge_deg  edge_price  edge_mul  edge_deg_extend  edge_block  \\\n",
       "2012-10-12         1           0        -1                0          -1   \n",
       "2012-10-12        -1           0         1                0          -1   \n",
       "2012-10-12         0          -1        -1                0          -1   \n",
       "2012-10-12        -1          -1         0                0          -1   \n",
       "2012-10-12         0          -1        -1                0          -1   \n",
       "\n",
       "            result  \n",
       "2012-10-12      -1  \n",
       "2012-10-12       1  \n",
       "2012-10-12      -1  \n",
       "2012-10-12      -1  \n",
       "2012-10-12       1  "
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "block_pd = order_has_result.filter(regex='^edge_*')\n",
    "\"\"\"\n",
    "    由于predict返回的结果中1代表win top\n",
    "    但是我们只需要知道loss_top，所以只保留-1, 其他1转换为0。\n",
    "\"\"\"\n",
    "block_pd['edge_block'] = \\\n",
    "    np.where(np.min(block_pd, axis=1) == -1, -1, 0)\n",
    "\n",
    "# 拿出真实的交易结果\n",
    "block_pd['result'] = order_has_result['result']\n",
    "# 拿出-1的结果，即判定loss_top的\n",
    "block_pd = block_pd[block_pd.edge_block == -1]\n",
    "\n",
    "\n",
    "print('四个裁判整体拦截正确率{:.2f}%'.format(block_pd[block_pd.result == -1].result.count() / \n",
    "                                  block_pd.result.count() * 100))\n",
    "\n",
    "print('四个边裁拦截交易总数{}， 拦截率{:.2f}%'.format(\n",
    "    block_pd.shape[0],\n",
    "    block_pd.shape[0] / order_has_result.shape[0] * 100))\n",
    "block_pd.head()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "下面再统计每一个 边裁的拦截正确率："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "角度边裁拦截正确率63.69%, 拦截交易数量1300\n",
      "单混边裁拦截正确率63.78%, 拦截交易数量1132\n",
      "价格边裁拦截正确率60.76%, 拦截交易数量1259\n",
      "角度扩展边裁拦截正确率67.08%, 拦截交易数量978\n"
     ]
    }
   ],
   "source": [
    "from sklearn import metrics\n",
    "def sub_edge_show(edge_name):\n",
    "    sub_edge_block_pd = order_has_result[(order_has_result[edge_name] == -1)]\n",
    "    return metrics.accuracy_score(sub_edge_block_pd[edge_name], sub_edge_block_pd.result) * 100, sub_edge_block_pd.shape[0]\n",
    "\n",
    "print('角度边裁拦截正确率{0:.2f}%, 拦截交易数量{1:}'.format(*sub_edge_show('edge_deg')))\n",
    "print('单混边裁拦截正确率{0:.2f}%, 拦截交易数量{1:}'.format(*sub_edge_show('edge_mul')))\n",
    "print('价格边裁拦截正确率{0:.2f}%, 拦截交易数量{1:}'.format(*sub_edge_show('edge_price')))\n",
    "print('角度扩展边裁拦截正确率{0:.2f}%, 拦截交易数量{1:}'.format(*sub_edge_show('edge_deg_extend')))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 4. 在abu系统中开启主裁拦截模式，开启边裁拦截模式\n",
    "\n",
    "内置边裁的开启很简单，只需要通过env中的相关设置即可完成，如下所示，分别开启主裁和边裁的两个内置裁判："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# 开启内置主裁\n",
    "abupy.env.g_enable_ump_main_deg_block = True\n",
    "abupy.env.g_enable_ump_main_price_block = True\n",
    "\n",
    "# 开启内置边裁\n",
    "abupy.env.g_enable_ump_edge_deg_block = True\n",
    "abupy.env.g_enable_ump_edge_price_block = True\n",
    "\n",
    "# 回测时需要开启特征生成，因为裁判开启需要生成特征做为输入\n",
    "abupy.env.g_enable_ml_feature = True\n",
    "# 回测时使用上一次切割好的测试集数据\n",
    "abupy.env.g_enable_last_split_test = True\n",
    "\n",
    "abupy.beta.atr.g_atr_pos_base = 0.05"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* 用户自定义裁判的开启在‘第18节 自定义裁判决策交易‘ 也示例过，通过ump.manager.append_user_ump即可\n",
    "\n",
    "* 注意下面还需要把10，30，50，90，120日走势拟合角度特征的AbuFeatureDegExtend，做为回测时的新的视角来录制比赛（记录回测特征），因为裁判里面有AbuUmpEegeDegExtend和AbuUmpMainDegExtend，它们需要生成带有10，30，50，90，120日走势拟合角度特征的回测交易单\n",
    "\n",
    "代码如下所示："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "feature.clear_user_feature()\n",
    "# 10，30，50，90，120日走势拟合角度特征的AbuFeatureDegExtend，做为回测时的新的视角来录制比赛\n",
    "feature.append_user_feature(AbuFeatureDegExtend)\n",
    "\n",
    "# 打开使用用户自定义裁判开关\n",
    "ump.manager.g_enable_user_ump = True\n",
    "# 先clear一下\n",
    "ump.manager.clear_user_ump()\n",
    "# 把新的裁判AbuUmpMainDegExtend类名称使用append_user_ump添加到系统中\n",
    "ump.manager.append_user_ump(AbuUmpEegeDegExtend)\n",
    "# 把新的裁判AbuUmpMainDegExtend类名称使用append_user_ump添加到系统中\n",
    "ump.manager.append_user_ump(AbuUmpMainDegExtend)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "买入因子，卖出因子等依然使用相同的设置，如下所示："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# 初始化资金500万\n",
    "read_cash = 5000000\n",
    "\n",
    "# 买入因子依然延用向上突破因子\n",
    "buy_factors = [{'xd': 60, 'class': AbuFactorBuyBreak},\n",
    "               {'xd': 42, 'class': AbuFactorBuyBreak}]\n",
    "\n",
    "# 卖出因子继续使用上一节使用的因子\n",
    "sell_factors = [\n",
    "    {'stop_loss_n': 1.0, 'stop_win_n': 3.0,\n",
    "     'class': AbuFactorAtrNStop},\n",
    "    {'class': AbuFactorPreAtrNStop, 'pre_atr_n': 1.5},\n",
    "    {'class': AbuFactorCloseAtrNStop, 'close_atr_n': 1.5}\n",
    "]\n",
    "abupy.env.g_market_target = EMarketTargetType.E_MARKET_TARGET_CN\n",
    "abupy.env.g_data_fetch_mode = EMarketDataFetchMode.E_DATA_FETCH_FORCE_LOCAL"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "完成裁判组合的开启，即可开始回测，回测操作流程和之前的操作一样：\n",
    "\n",
    "下面开始回测，第一次运行select：run loop back ump，然后点击run select_ump，如果已经回测过可select：load test ump data直接从缓存数据读取："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "please wait! load_pickle....: /Users/Bailey/abu/data/cache/n5_test_ump_cn_capital\n",
      "please wait! load_pickle....: /Users/Bailey/abu/data/cache/n5_test_ump_cn_benchmark\n"
     ]
    }
   ],
   "source": [
    "abupy.env.g_market_target = EMarketTargetType.E_MARKET_TARGET_CN\n",
    "abupy.env.g_data_fetch_mode = EMarketDataFetchMode.E_DATA_FETCH_FORCE_LOCAL\n",
    "\n",
    "abu_result_tuple_test_ump = None\n",
    "def run_loop_back_ump():\n",
    "    global abu_result_tuple_test_ump\n",
    "    abu_result_tuple_test_ump, _ = abu.run_loop_back(read_cash,\n",
    "                                                 buy_factors,\n",
    "                                                 sell_factors,\n",
    "                                                 choice_symbols=None,\n",
    "                                                 start='2012-08-08', end='2017-08-08')\n",
    "    # 把运行的结果保存在本地，以便之后分析回测使用，保存回测结果数据代码如下所示\n",
    "    abu.store_abu_result_tuple(abu_result_tuple_test_ump, n_folds=5, store_type=EStoreAbu.E_STORE_CUSTOM_NAME, \n",
    "                               custom_name='test_ump_cn')\n",
    "    ABuProgress.clear_output()\n",
    "\n",
    "def run_load_ump():\n",
    "    global abu_result_tuple_test_ump\n",
    "    abu_result_tuple_test_ump = abu.load_abu_result_tuple(n_folds=5, store_type=EStoreAbu.E_STORE_CUSTOM_NAME, \n",
    "                                                 custom_name='test_ump_cn')\n",
    "\n",
    "def select_ump(select):\n",
    "    if select == 'run loop back ump':\n",
    "        run_loop_back_ump()\n",
    "    else:\n",
    "        run_load_ump()\n",
    "\n",
    "_ = ipywidgets.interact_manual(select_ump, select=['run loop back ump', 'load test ump data'])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "下面对比针对A股市场测试集交易开启主裁，边裁拦截和未开启主裁，边裁，结果可以看出拦截了接近一半的交易，胜率以及盈亏比都有大幅度提高："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "买入后卖出的交易数量:3465\n",
      "买入后尚未卖出的交易数量:41\n",
      "胜率:54.3146%\n",
      "平均获利期望:17.1289%\n",
      "平均亏损期望:-6.8200%\n",
      "盈亏比:3.1242\n",
      "所有交易收益比例和:214.2996 \n",
      "所有交易总盈亏和:82209541.5500 \n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "<abupy.MetricsBu.ABuMetricsBase.AbuMetricsBase at 0x1401d2160>"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "AbuMetricsBase.show_general(*abu_result_tuple_test_ump, returns_cmp=True, only_info=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "买入后卖出的交易数量:6321\n",
      "买入后尚未卖出的交易数量:124\n",
      "胜率:47.6507%\n",
      "平均获利期望:15.7211%\n",
      "平均亏损期望:-7.6456%\n",
      "盈亏比:2.0477\n",
      "所有交易收益比例和:221.5061 \n",
      "所有交易总盈亏和:44078404.6500 \n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "<abupy.MetricsBu.ABuMetricsBase.AbuMetricsBase at 0x1401d2a20>"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "AbuMetricsBase.show_general(*abu_result_tuple_test, returns_cmp=True, only_info=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "#### abu量化文档目录章节\n",
    "\n",
    "1. [择时策略的开发](http://www.abuquant.com/lecture/lecture_1.html)\n",
    "2. [择时策略的优化](http://www.abuquant.com/lecture/lecture_2.html)\n",
    "3. [滑点策略与交易手续费](http://www.abuquant.com/lecture/lecture_3.html)\n",
    "4. [多支股票择时回测与仓位管理](http://www.abuquant.com/lecture/lecture_4.html)\n",
    "5. [选股策略的开发](http://www.abuquant.com/lecture/lecture_5.html)\n",
    "6. [回测结果的度量](http://www.abuquant.com/lecture/lecture_6.html)\n",
    "7. [寻找策略最优参数和评分](http://www.abuquant.com/lecture/lecture_7.html)\n",
    "8. [A股市场的回测](http://www.abuquant.com/lecture/lecture_8.html)\n",
    "9. [港股市场的回测](http://www.abuquant.com/lecture/lecture_9.html)\n",
    "10. [比特币，莱特币的回测](http://www.abuquant.com/lecture/lecture_10.html)\n",
    "11. [期货市场的回测](http://www.abuquant.com/lecture/lecture_11.html)\n",
    "12. [机器学习与比特币示例](http://www.abuquant.com/lecture/lecture_12.html)\n",
    "13. [量化技术分析应用](http://www.abuquant.com/lecture/lecture_13.html)\n",
    "14. [量化相关性分析应用](http://www.abuquant.com/lecture/lecture_14.html)\n",
    "15. [量化交易和搜索引擎](http://www.abuquant.com/lecture/lecture_15.html)\n",
    "16. [UMP主裁交易决策](http://www.abuquant.com/lecture/lecture_16.html)\n",
    "17. [UMP边裁交易决策](http://www.abuquant.com/lecture/lecture_17.html)\n",
    "18. [自定义裁判决策交易](http://www.abuquant.com/lecture/lecture_18.html)\n",
    "19. [数据源](http://www.abuquant.com/lecture/lecture_19.html)\n",
    "20. [A股全市场回测](http://www.abuquant.com/lecture/lecture_20.html)\n",
    "21. [A股UMP决策](http://www.abuquant.com/lecture/lecture_21.html)\n",
    "22. [美股全市场回测](http://www.abuquant.com/lecture/lecture_22.html)\n",
    "23. [美股UMP决策](http://www.abuquant.com/lecture/lecture_23.html)\n",
    "\n",
    "abu量化系统文档教程持续更新中，请关注公众号中的更新提醒。\n",
    "\n",
    "#### 《量化交易之路》目录章节及随书代码地址\n",
    "\n",
    "1. [第二章 量化语言——Python](https://github.com/bbfamily/abu/tree/master/ipython/第二章-量化语言——Python.ipynb)\n",
    "2. [第三章 量化工具——NumPy](https://github.com/bbfamily/abu/tree/master/ipython/第三章-量化工具——NumPy.ipynb)\n",
    "3. [第四章 量化工具——pandas](https://github.com/bbfamily/abu/tree/master/ipython/第四章-量化工具——pandas.ipynb)\n",
    "4. [第五章 量化工具——可视化](https://github.com/bbfamily/abu/tree/master/ipython/第五章-量化工具——可视化.ipynb)\n",
    "5. [第六章 量化工具——数学：你一生的追求到底能带来多少幸福](https://github.com/bbfamily/abu/tree/master/ipython/第六章-量化工具——数学.ipynb)\n",
    "6. [第七章 量化系统——入门：三只小猪股票投资的故事](https://github.com/bbfamily/abu/tree/master/ipython/第七章-量化系统——入门.ipynb)\n",
    "7. [第八章 量化系统——开发](https://github.com/bbfamily/abu/tree/master/ipython/第八章-量化系统——开发.ipynb)\n",
    "8. [第九章 量化系统——度量与优化](https://github.com/bbfamily/abu/tree/master/ipython/第九章-量化系统——度量与优化.ipynb)\n",
    "9. [第十章 量化系统——机器学习•猪老三](https://github.com/bbfamily/abu/tree/master/ipython/第十章-量化系统——机器学习•猪老三.ipynb)\n",
    "10. [第十一章 量化系统——机器学习•ABU](https://github.com/bbfamily/abu/tree/master/ipython/第十一章-量化系统——机器学习•ABU.ipynb)\n",
    "11. [附录A 量化环境部署](https://github.com/bbfamily/abu/tree/master/ipython/附录A-量化环境部署.ipynb)\n",
    "12. [附录B 量化相关性分析](https://github.com/bbfamily/abu/tree/master/ipython/附录B-量化相关性分析.ipynb)\n",
    "13. [附录C 量化统计分析及指标应用](https://github.com/bbfamily/abu/tree/master/ipython/附录C-量化统计分析及指标应用.ipynb)\n",
    "\n",
    "[更多阿布量化量化技术文章](http://www.abuquant.com/article)\n",
    "\n",
    "更多关于量化交易相关请阅读[《量化交易之路》](http://www.abuquant.com/books/quantify-trading-road.html)\n",
    "\n",
    "更多关于量化交易与机器学习相关请阅读[《机器学习之路》](http://www.abuquant.com/books/machine-learning-road.html)\n",
    "\n",
    "更多关于abu量化系统请关注微信公众号: abu_quant\n",
    "\n",
    "![](./image/qrcode.jpg)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
